#pragma once 
#define  _WINSOCK_DEPRECATED_NO_WARNINGS
#include "xx_com.hpp"
#include "winsock2.h"
#include "WS2tcpip.h"
#include <string>
using namespace std;

typedef unsigned int ip_t;
typedef unsigned short port_t;
typedef uint32_t in_addr_t;


#pragma comment(lib,"WS2_32.lib")
#define  INIT_NET WSADATA d;WSAStartup(MAKEWORD(2,2),&d);


static sockaddr_in fill_addr(const char* ip, port_t port)
{
	sockaddr_in addr;
	memset(&addr, 0, sizeof(sockaddr_in));
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	addr.sin_addr.s_addr = inet_addr(ip);
	return addr;
}
static ip_t get_addr_ip(sockaddr_in* addr) {
	return addr->sin_addr.s_addr;
}

static port_t get_addr_port(sockaddr_in* addr) {
	return htons(addr->sin_port);
}

static string get_addr_str(sockaddr_in* addr) {
	char sz[100] = { 0 };
	inet_ntop(AF_INET, (void*)&addr->sin_addr, sz, 100);
	string ret = string(sz) + ":" + to_string(get_addr_port(addr));
	return  ret;
}

class xsock
{
public:
	void close() {
		if (INVALID_SOCKET == sock_) {
			return;
		}
		::closesocket(sock_);
		sock_ = INVALID_SOCKET;
	}

	bool tcp_create() {
		close();
		sock_ = ::socket(AF_INET, SOCK_STREAM, 0);
		X_CHECK_RET_BOOL(INVALID_SOCKET != sock_);
		return true;
	}

	bool connect(const char* ip, port_t port) {
		sockaddr_in addr = fill_addr(ip, port);
		auto ret = ::connect(sock_, (struct sockaddr*)&addr, sizeof(addr));
		if (-1 == ret && errno != EINPROGRESS)
		{
			X_CHECK_RET_BOOL(false);
		}

		return true;
	}

	bool set_nonblock(int32_t value)
	{
		u_long ul = value;
		X_CHECK_RET_BOOL(0 == ioctlsocket(sock_, FIONBIO, &ul), false);
		return true;
	}
public:
	SOCKET sock_{ INVALID_SOCKET };
};